﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BISPOS.Repository
{
    public class InvoiceRepository
    {
        BISPOSDataClassesDataContext db = new BISPOSDataClassesDataContext();
        ProductRepository productRepository = new ProductRepository();
        StockRepository stockRepository = new StockRepository();
        public int startNumber = 0;
        public Invoice LatestInvoice()
        {
            if (db.Invoices.Count() != 0)
                return db.Invoices.OrderByDescending(x => x.Id).FirstOrDefault();
            else
                return null;
        }
        public string LatestInvoiceNumber()
        {
            if (db.Invoices.Count() > 0)
            {
                int id = db.Invoices.LastOrDefault().Id;
                string no = "A" + (DateTime.Now.Year + 543 - 2500).ToString() +
                    (id+startNumber).ToString().PadLeft(6, '0');
                return no;
            }
            else
            {
                return "A" + (DateTime.Now.Year + 543 - 2500).ToString() +
                    (startNumber).ToString().PadLeft(6, '0');
            }
        }
        public int LatestInvoiceId()
        {
            return db.Invoices.LastOrDefault().Id;
        }
        public string NextInvoiceNumber()
        {
            if (db.Invoices.Count() > 0)
            {
                int id = db.Invoices.LastOrDefault().Id;
                string no = "A" + (DateTime.Now.Year + 543 - 2500).ToString() +
                    (id +1+ startNumber).ToString().PadLeft(6, '0');
                return no;
            }
            else
            {
                return "A" + (DateTime.Now.Year + 543 - 2500).ToString() +
                    (startNumber+1).ToString().PadLeft(6, '0');
            }
        }
        public IEnumerable<Invoice> GetInvoices(DateTime fromDate, DateTime toDate)
        {
            return db.Invoices.Where(x => (x.Date.Date >= fromDate.Date) && (x.Date.Date <= toDate.Date)).OrderByDescending(x => x.Date); 
        }
        public IEnumerable<Invoice> GetActiveInvoices(DateTime fromDate,DateTime toDate)
        {
            return db.Invoices.Where(x => (x.Date.Date >= fromDate.Date) && (x.Date.Date <= toDate.Date)&&x.IsActive).OrderByDescending(x => x.Date);
        }
        public IEnumerable<Invoice> GetInActiveInvoices(DateTime fromDate, DateTime toDate)
        {
            return db.Invoices.Where(x => (x.Date.Date >= fromDate.Date) && (x.Date.Date <= toDate.Date) && !x.IsActive).OrderByDescending(x => x.Date);
        }
        public IEnumerable<InvoiceItem> GetInvoiceItems(int productId, DateTime date)
        {
            return db.InvoiceItems.Where(x =>
                (x.Invoice.Date.Date == date.Date) && (x.Stock.ProductId == productId));
        }
        public Invoice GetInvoice(int id)
        {
            return this.db.Invoices.FirstOrDefault(x => x.Id == id);
        }
        public PaymentType DefaultPaymentType() { return db.PaymentTypes.FirstOrDefault(x => x.Id == 1); }
        public IEnumerable<PaymentType> AllPaymentTypes() { return db.PaymentTypes.OrderBy(x => x.Id); }
        public void CreateInvoice(int paymentTypeId, int employeeId, int? customerId,
            decimal paid, string note, IEnumerable<POSGridItem> posGridItems)
        {
            Invoice invoice = new Invoice
            {
                CustomerId = customerId,
                Date = DateTime.Now,
                EmployeeId = employeeId,
                IsActive = true,
                Note = note,
                Paid = paid,
                PaymentTypeId = paymentTypeId
            };
            foreach (var posGridItem in posGridItems)
            {
                double quantity = posGridItem.Quantity;
                do
                {
                    productRepository = new ProductRepository();
                    Product product = productRepository.Get(posGridItem.ProductId);
                    if (product.IsAvailableStock)
                    {
                        if (product.FirstAvailableStock.CurrentQuantity > 0)
                        {
                            if (product.FirstAvailableStock.CurrentQuantity >= quantity)
                            {
                                int stockId = stockRepository.SubtractStock(product.FirstAvailableStock.Id, quantity);
                                invoice.InvoiceItems.Add(new InvoiceItem
                                {
                                    PriceId = posGridItem.PriceId,
                                    Quantity = quantity,
                                    StockId = stockId
                                });
                                quantity = 0;
                            }
                            else
                            {
                                double subtractedQuantity = product.FirstAvailableStock.CurrentQuantity;
                                int stockId = stockRepository.SubtractStock(product.FirstAvailableStock.Id, subtractedQuantity);
                                invoice.InvoiceItems.Add(new InvoiceItem
                                {
                                    PriceId = posGridItem.PriceId,
                                    Quantity = subtractedQuantity,
                                    StockId = stockId
                                });
                                quantity -= subtractedQuantity;

                            }
                        }
                        else
                        {
                            int stockId = stockRepository.SubtractStock(product.FirstAvailableStock.Id, quantity);
                            invoice.InvoiceItems.Add(new InvoiceItem
                            {
                                PriceId = posGridItem.PriceId,
                                Quantity = quantity,
                                StockId = stockId
                            });
                            quantity = 0;
                        }
                    }
                    else
                    {
                        
                        invoice.InvoiceItems.Add(new InvoiceItem
                        {
                            PriceId = posGridItem.PriceId,
                            Quantity = quantity,
                            StockId = stockRepository.AddNewStock(product.Id,0,-quantity,0,DateTime.Now).Id
                        });
                        quantity = 0;
                    }
                } while (quantity > 0);
            }
            db.Invoices.InsertOnSubmit(invoice);
            db.SubmitChanges();
        }
        public void VoidInvoice(int id)
        {
            Invoice invoice = GetInvoice(id);
            invoice.IsActive = false;
            db.SubmitChanges();
            foreach (var item in invoice.InvoiceItems)
            {
                Stock stock = stockRepository.GetStock(item.StockId);
                {
                    stock.CurrentQuantity += item.Quantity;
                    stockRepository.Save();
                }
            }

        }
    }
}
